
package com.hlkj.pay.app.openapi.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.pay.app.openapi.IOpenApiAppService;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.dto.LocalMerchantRequest;
import com.hlkj.pay.dto.common.RsaConfig;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.service.common.IPlatFormConfigService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.util.SignUtils;
import com.hlkj.pay.vo.order.OpenApiResult;
import com.hlkj.pay.vo.order.req.OrderCommonParamReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @author HlpayTeam
 * @date 2024/10/09 13:52
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OpenApiAppServiceImpl implements IOpenApiAppService<T> {

    private final IMerchantApplicationService merchantApplicationService;

    private final IMerchantService merchantService;

    private final IPlatFormConfigService platFormConfigService;

    private final IPayOrderService payOrderService;

    @Value("${hlkj.pay.openapi.checkTime:true}")
    private boolean checkTime;

    @Value("${hlkj.pay.openapi.checkSign:true}")
    private boolean checkSign;

    @Override
    public CommonResult<Void> checkApp(OrderCommonParamReq orderCommonParamReq) {
        String timestampString = orderCommonParamReq.getTimestamp();
        Long currentTimeMillis = System.currentTimeMillis();
        long nowTime = currentTimeMillis / 1000;
        // 小于当前时间 并且60s以内有效
        Long timestamp = Long.valueOf(timestampString);
        long time = timestamp - nowTime;
        if (Math.abs(time) > 60 && checkTime) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_DATETIME_ERROR);
        }
        MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(orderCommonParamReq.getAppId());
        if (merchantAppDO == null) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EFFECT);
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String clientIP = ServletUtil.getClientIP(request, null);
        if (StringUtils.hasText(merchantAppDO.getIpConfig()) && !merchantAppDO.getIpConfig().contains("0.0.0.0") && !merchantAppDO.getIpConfig().contains(clientIP)) {
            return CommonResult.error(OpenApiResultCode.CHANNEL_IP_NOT_EFFECT);
        }
        String sn = merchantAppDO.getSn();
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
        if (merchantInfoDO == null) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EFFECT);
        }

        // 签名参数
        Map<String, Object> map = BeanUtil.beanToMap(orderCommonParamReq);
        if (!StringUtils.hasText(merchantAppDO.getPublicKey())) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_PUBLIC_KEY_NOT_EFFECT);
        }
        if (!"RSA2".equals(orderCommonParamReq.getSignType())) {
            return CommonResult.error(OpenApiResultCode.MERCHANT_SIGN_TYPE_ERROR);
        }
        // map.put("sign","We8yziDUNtcj00AFbXvgXHxSYuEYnzEHSBD01enrzY+TaZZGbHsjovWDPKsFrt0e33sq3BDoyd5qYJJ+dPjC66oMqxsw3ntmlu5+qTNYdRNFa9LuGXx4MSwPE+DIcbkg4Ibx21qniEXlCX5LDZCtZat9boxrqDlbyf5rU+HR44chRhQDUvQdXTX60tp/LxttG/P2EZt2YZxOCrdjDtgUXLIX8igClMcf9k9cFsjlTWoOXRMmzp8xnUrLMsJ1PYc2jQ9w25GcjZhy5Vp3miGLAqMK/kGJaavaGyHHnmWjQiE2SUL68ZMjY6TD+MC/8zFdPErZ+f856KP6Ss02CnlO2A==");
        try {
            boolean verifySign = SignUtils.verify(map, merchantAppDO.getPublicKey());
            if (!verifySign && checkSign) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_SIGN_ERROR);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("publicKey error", merchantAppDO.getPublicKey());
            return CommonResult.error(OpenApiResultCode.MERCHANT_SIGN_ERROR);
        }
        // 取子商户id 如果有
        if (StringUtils.hasText(orderCommonParamReq.getSubSn())) {
            merchantAppDO = merchantApplicationService.queryDefaultApp(orderCommonParamReq.getSubSn());
            if (merchantAppDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EFFECT);
            }
            merchantInfoDO = merchantService.queryMerchant(sn);
            if (merchantInfoDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EFFECT);
            }
            if (!sn.equals(merchantInfoDO.getSuperAgent())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EFFECT);
            }
        }
        LocalMerchantRequest localMerchantRequest = (LocalMerchantRequest) LocalContext.get();
        if (localMerchantRequest == null) {
            localMerchantRequest = new LocalMerchantRequest();
        }
        localMerchantRequest.setMerchantAppDO(merchantAppDO);
        localMerchantRequest.setMerchantInfoDO(merchantInfoDO);
        localMerchantRequest.setSn(sn);
        localMerchantRequest.setSubSn(orderCommonParamReq.getSubSn());
        localMerchantRequest.setAppId(merchantAppDO.getAppId());
        localMerchantRequest.setSignType(orderCommonParamReq.getSignType());
        LocalContext.set(localMerchantRequest);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> setAppInfo(String appId) {
        if (!StringUtils.hasText(appId)) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EXIST);
        }
        MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(appId);
        if (merchantAppDO == null) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EFFECT);
        }
        String sn = merchantAppDO.getSn();
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
        if (merchantInfoDO == null) {
            return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
            return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EFFECT);
        }
        // 改写线程数据
        LocalMerchantRequest localMerchantRequest = new LocalMerchantRequest();
        localMerchantRequest.setMerchantAppDO(merchantAppDO);
        localMerchantRequest.setMerchantInfoDO(merchantInfoDO);
        localMerchantRequest.setSn(sn);
        localMerchantRequest.setSysType(merchantAppDO.getSysType());
        localMerchantRequest.setAppId(merchantAppDO.getAppId());
        LocalContext.set(localMerchantRequest);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> setAppInfoOnly(String appId) {
        if (!StringUtils.hasText(appId)) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EXIST);
        }
        MerchantAppDO merchantAppDO = merchantApplicationService.getByAppId(appId);
        if (merchantAppDO == null) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
            return CommonResult.error(MerchantResultCode.MERCHANT_APP_NOT_EFFECT);
        }
        String sn = merchantAppDO.getSn();
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
        if (merchantInfoDO == null) {
            return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EXIST);
        }
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
            return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EFFECT);
        }
        // 改写线程数据
        LocalMerchantRequest localMerchantRequest = new LocalMerchantRequest();
        localMerchantRequest.setMerchantAppDO(merchantAppDO);
        localMerchantRequest.setMerchantInfoDO(merchantInfoDO);
        localMerchantRequest.setSn(sn);
        localMerchantRequest.setSysType(merchantAppDO.getSysType());
        localMerchantRequest.setAppId(merchantAppDO.getAppId());
        LocalContext.set(localMerchantRequest);
        return CommonResult.success();
    }

    // @Override
    // public OpenApiResult<Object> sign(OpenApiResult<Object> commonResult) {
    // LocalMerchantRequest
    // localMerchantRequest=(LocalMerchantRequest)LocalContext.get();
    // commonResult.setSignType(localMerchantRequest.getSignType());
    // commonResult.setAppId(localMerchantRequest.getAppId());
    // commonResult.setSn(localMerchantRequest.getSn());
    // commonResult.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
    // if (commonResult.getData() != null) {
    // RsaConfig rsaConfig = platFormConfigService.getRsaConfig();
    // // 签名参数
    // Map<String, Object> map = BeanUtil.beanToMap(commonResult);
    // try {
    // String sign = SignUtils.signRsa(map, rsaConfig.getPrivateKey(),
    // commonResult.getSignType());
    // commonResult.setSign(sign);
    // }
    // catch (Exception e) {
    // log.error("sign error");
    // // throw new RuntimeException(e);
    // }
    // }
    // return commonResult;
    // }
    @Override
    public OpenApiResult sign(OpenApiResult commonResult) {
        LocalMerchantRequest localMerchantRequest = (LocalMerchantRequest) LocalContext.get();
        OpenApiResult objectOpenApiResult = new OpenApiResult<>();
        objectOpenApiResult.setData(commonResult.getData());
        objectOpenApiResult.setCode(commonResult.getCode());
        objectOpenApiResult.setMsg(commonResult.getMsg());
        if (commonResult.isSuccess()) {
            objectOpenApiResult.setSignType(localMerchantRequest.getSignType());
            objectOpenApiResult.setAppId(localMerchantRequest.getAppId());
            objectOpenApiResult.setSn(localMerchantRequest.getSn());
            objectOpenApiResult.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
            if (objectOpenApiResult.getData() != null) {
                RsaConfig rsaConfig = platFormConfigService.getRsaConfig();
                // 签名参数
                Map<String, Object> map = BeanUtil.beanToMap(objectOpenApiResult);
                try {
                    String sign = SignUtils.signRsa(map, rsaConfig.getPrivateKey(), objectOpenApiResult.getSignType());
                    objectOpenApiResult.setSign(sign);
                }
                catch (Exception e) {
                    log.error("sign error");
                    // throw new RuntimeException(e);
                }
            }
        }
        return objectOpenApiResult;
    }

    @Override
    public OpenApiResult sign(CommonResult commonResult) {
        LocalMerchantRequest localMerchantRequest = (LocalMerchantRequest) LocalContext.get();
        OpenApiResult objectOpenApiResult = new OpenApiResult<>();
        objectOpenApiResult.setData(commonResult.getData());
        objectOpenApiResult.setCode(commonResult.getCode());
        objectOpenApiResult.setMsg(commonResult.getMsg());
        if (commonResult.isSuccess()) {
            objectOpenApiResult.setSignType(localMerchantRequest.getSignType());
            objectOpenApiResult.setAppId(localMerchantRequest.getAppId());
            objectOpenApiResult.setSn(localMerchantRequest.getSn());
            objectOpenApiResult.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
            if (objectOpenApiResult.getData() != null) {
                RsaConfig rsaConfig = platFormConfigService.getRsaConfig();
                // 签名参数
                Map<String, Object> map = BeanUtil.beanToMap(objectOpenApiResult);
                try {
                    String sign = SignUtils.signRsa(map, rsaConfig.getPrivateKey(), objectOpenApiResult.getSignType());
                    objectOpenApiResult.setSign(sign);
                }
                catch (Exception e) {
                    log.error("sign error");
                    // throw new RuntimeException(e);
                }
            }
        }
        return objectOpenApiResult;
    }

    public static String pubKey() {
        // return
        // "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgwShs3d8dqtyYtGT1yAvSKGf/6oTKUQ4ZVQ0F+Q6w9r8EVNBrnkDW8wY0UtPgRDHUFYhdjs1+RuTFkgTxgRc7S3tZlZ4232mQneH7QynpbfuN0Uw93jVkofSf3mfPtYT1L5tiPA4DczHr+4jyAcOwZ4TuqIoP1thbnT87DjkaUNCBtTgcMBYh9VmWfKA5qsdrww257E9S57F18CiEVidfj/ASpQV51WcxtxGwVFCBW08JQEweYXJxRuRqBai8EhTqKzSCxTa5MlxIvNV+z4ka9Ioa1wkgCNrLxc22u/QiRjCMjlKEsALPf1IV973hhmbhQDQA4ZW25/3WIqM4s+a9QIDAQAB
        return "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgwShs3d8dqtyYtGT1yAvSKGf/6oTKUQ4ZVQ0F+Q6w9r8EVNBrnkDW8wY0UtPgRDHUFYhdjs1+RuTFkgTxgRc7S3tZlZ4232mQneH7QynpbfuN0Uw93jVkofSf3mfPtYT1L5tiPA4DczHr+4jyAcOwZ4TuqIoP1thbnT87DjkaUNCBtTgcMBYh9VmWfKA5qsdrww257E9S57F18CiEVidfj/ASpQV51WcxtxGwVFCBW08JQEweYXJxRuRqBai8EhTqKzSCxTa5MlxIvNV+z4ka9Ioa1wkgCNrLxc22u/QiRjCMjlKEsALPf1IV973hhmbhQDQA4ZW25/3WIqM4s+a9QIDAQAB";
    }
}
